package com.lp.biz.operations.service.impl;
import java.math.BigDecimal;
import java.time.LocalDateTime;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.pagehelper.PageHelper;
import com.lp.biz.content.mapper.BizCoreContentMapper;
import com.lp.biz.content.mapper.BizCoreContentMemberRelMapper;
import com.lp.biz.content.model.entity.BizCoreContent;
import com.lp.biz.content.model.entity.BizCoreContentMemberRel;
import com.lp.biz.identity.mapper.AdvisorMapper;
import com.lp.biz.identity.mapper.AdvisorMemberRelMapper;
import com.lp.biz.identity.model.entity.Advisor;
import com.lp.biz.identity.model.entity.AdvisorMemberRel;
import com.lp.biz.member.model.entity.Member;
import com.lp.biz.member.service.MemberService;
import com.lp.biz.members.mapper.BizMembersMapper;
import com.lp.biz.members.mapper.BizMembersRelMapper;
import com.lp.biz.members.model.entity.BizMembers;
import com.lp.biz.members.model.entity.BizMembersRel;
import com.lp.biz.message.service.BizMessageSystemService;
import com.lp.biz.operations.model.entity.BizBenefits;
import com.lp.biz.operations.mapper.BizBenefitsMapper;
import com.lp.biz.operations.model.vo.BenefitsAdd;
import com.lp.biz.operations.model.vo.BenefitsContent;
import com.lp.biz.operations.service.BizBenefitsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lp.common.component.RedisService;
import com.lp.common.entity.PageParams;
import com.lp.common.exception.BaseException;
import com.lp.common.utils.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import static com.lp.common.constant.AdvisorConstant.ADVISOR_TYPE_CODE;
import static com.lp.common.constant.CacheConstant.BIZ_USER_DETAIL_KEY;
import static com.lp.common.constant.CategoryConstant.CODE_COURSE;
import static com.lp.common.constant.CategoryConstant.CODE_TRAINING;
import static com.lp.common.constant.CommonConstant.*;
import static com.lp.common.constant.MembersConst.*;

/**
 * @program: backend
 * @description: BizBenefits 服务实现类
 * @author Ke.Song
 * @since 2024-09-03 23:54:13
 */
@Slf4j
@Service
public class BizBenefitsServiceImpl extends ServiceImpl<BizBenefitsMapper, BizBenefits> implements BizBenefitsService {

    @Autowired
    private RedisService redis;

    @Autowired
    private MemberService memberService;

    @Autowired
    private AdvisorMapper advisorMapper;

    @Autowired
    private BizMembersMapper membersMapper;

    @Autowired
    private BizMembersRelMapper membersRelMapper;

    @Autowired
    private BizCoreContentMapper coreContentMapper;

    @Autowired
    private BizMessageSystemService messageSystemService;

    @Autowired
    private AdvisorMemberRelMapper advisorMemberRelMapper;

    @Autowired
    private BizCoreContentMemberRelMapper contentMemberRelMapper;

    @Override
    public CommonResult getContentList() {
        List<BenefitsContent> result = new ArrayList<>();
        for (BizMembers members : membersMapper.selectList(new QueryWrapper<>())) {
            BenefitsContent content = new BenefitsContent();
            content.setId(members.getId());
            if (members.getType().equals(TYPE_MONTH)) {
                content.setTitle("月卡");
            } else if (members.getType().equals(TYPE_QUARTER)) {
                content.setTitle("季卡");
            } else if (members.getType().equals(TYPE_YEAR)) {
                content.setTitle("年卡");
            }
            content.setCategoryCode(MEMBERS_CODE);
            result.add(content);
        }
        for (Advisor advisor : advisorMapper.selectList(new QueryWrapper<>())) {
            BenefitsContent content = new BenefitsContent();
            content.setId(advisor.getId());
            content.setTitle(advisor.getName());
            content.setCategoryCode(ADVISOR_TYPE_CODE);
            result.add(content);
        }
        for (BizCoreContent content : coreContentMapper.selectList(new QueryWrapper<BizCoreContent>().lambda()
                        .in(BizCoreContent::getBizCategoryCode, CODE_TRAINING, CODE_COURSE)
                .eq(BizCoreContent::getIsDisplay, SURE).eq(BizCoreContent::getIsDeleted, NEGATE)
                .orderByAsc(BizCoreContent::getBizCategoryCode).orderByAsc(BizCoreContent::getCreateAt))) {
            BenefitsContent benefitsContent = new BenefitsContent();
            benefitsContent.setId(content.getId());
            benefitsContent.setTitle(content.getTitle());
            benefitsContent.setCategoryCode(content.getBizCategoryCode());
            result.add(benefitsContent);
        }
        return CommonResult.success(result);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void addBenefits(BenefitsAdd params) {
        Member member = memberService.getById(params.getMemberId());
        if (member == null) {
            throw new BaseException("用户选择错误");
        }
        BizBenefits bizBenefits = new BizBenefits();
        bizBenefits.setMemberId(params.getMemberId());
        bizBenefits.setBizContentId(params.getContentId());
        bizBenefits.setBizCategoryCode(params.getCategoryCode());
        bizBenefits.setCreateAt(LocalDateTime.now());
        redis.delete(BIZ_USER_DETAIL_KEY + member.getId());
        if (params.getCategoryCode().equals(MEMBERS_CODE)) {
            BizMembers members = membersMapper.selectById(params.getContentId());
            if (members == null) {
                throw new BaseException("内容输入错误");
            }
            addMembers(member, members);
        } else if (params.getCategoryCode().equals(CODE_TRAINING) || params.getCategoryCode().equals(CODE_COURSE)) {
            addCoreContent(member, params);
        } else if (params.getCategoryCode().equals(ADVISOR_TYPE_CODE)) {
            addAdvisor(member, params);
        } else {
            throw new BaseException("内容输入错误");
        }
        save(bizBenefits);
    }

    @Override
    public CommonResult getBenefits(PageParams query) {
        PageHelper.startPage(query.getPage(), query.getSize());
        return CommonResult.restPage(baseMapper.getBenefits());
    }

    private void addMembers(Member member, BizMembers members) {
        Integer oldIsMembers = member.getIsMembers();
        LocalDate oldExpiryAt = member.getMembersExpiryAt();
        // 获取当前日期
        LocalDate now = LocalDate.now();
        // 初始化权益结束日期
        LocalDate end;
        // 判断会员是否为有效会员，并计算权益开始时间
        boolean isMembers = member.getIsMembers() != null && !member.getIsMembers().equals(NEGATE);
        LocalDate start = member.getMembersExpiryAt() == null ?  now: (isMembers ? member.getMembersExpiryAt() : now);

        // 根据会员类型，更新会员权益到期时间，并计算权益结束时间
        if (members.getType().equals(TYPE_MONTH)) {
            end = start.plusMonths(1);
        } else if (members.getType().equals(TYPE_QUARTER)) {
            end = start.plusMonths(3);
        } else if (members.getType().equals(TYPE_YEAR)) {
            end = start.plusYears(1);
        } else {
            log.info("开通权益：[{}]增加会员权益，没有对应会员包{}", member.getNickName(), members.getId());
            throw new BaseException("内容输入错误");
        }
        member.setIsMembers(SURE);
        member.setMembersExpiryAt(end);
        boolean update = memberService.update(null, new UpdateWrapper<Member>().lambda()
                .eq(Member::getId, member.getId()).eq(Member::getIsMembers, oldIsMembers)
                .eq(oldExpiryAt != null, Member::getMembersExpiryAt, oldExpiryAt)
                .isNull(oldExpiryAt == null, Member::getMembersExpiryAt)
                .set(Member::getIsMembers, member.getIsMembers())
                .set(Member::getMembersExpiryAt, member.getMembersExpiryAt()));
        if (!update) {
            member = memberService.getById(member.getId());
            addMembers(member, members);
        } else {
            // 创建会员权益关系对象，并设置相关属性
            BizMembersRel rel = new BizMembersRel();
            rel.setBizMembersId(members.getId());
            rel.setMemberId(member.getId());
            rel.setStartAt(start.plusDays(isMembers ? 1 : 0));
            rel.setEndAt(end);
            rel.setCreateAt(LocalDateTime.now());
            rel.setIsExpired(SURE);
            membersRelMapper.insert(rel);
            // 删除旧的用户详情缓存
            redis.delete(BIZ_USER_DETAIL_KEY + member.getId());
            log.info("开通权益：[{}]增加会员权益，有限期至：{}", member.getNickName(), member.getMembersExpiryAt());
        }
    }

    private void addCoreContent(Member member, BenefitsAdd params) {
        BizCoreContent content = coreContentMapper.selectById(params.getContentId());
        if (content == null || !content.getBizCategoryCode().equals(params.getCategoryCode()) ||
                content.getIsDeleted().equals(SURE) || content.getIsDisplay().equals(NEGATE)) {
            throw new BaseException("内容输入错误");
        }
        Long l = contentMemberRelMapper.selectCount(new QueryWrapper<BizCoreContentMemberRel>().lambda()
                .eq(BizCoreContentMemberRel::getMemberId, member.getId())
                .eq(BizCoreContentMemberRel::getBizCoreContentId, params.getContentId()));
        if (l != null && l > 0) {
            throw new BaseException(String.format("已拥有该%s", params.getCategoryCode().equals(CODE_TRAINING) ? "训练营": "课程"));
        }
        BizCoreContentMemberRel rel = new BizCoreContentMemberRel();
        rel.setBizCoreContentId(content.getId());
        rel.setBizCategoryId(content.getBizCategoryId());
        rel.setBizCategoryCode(content.getBizCategoryCode());
        rel.setMemberId(member.getId());
        rel.setCreateAt(LocalDateTime.now());
        contentMemberRelMapper.insert(rel);
        redis.delete(BIZ_USER_DETAIL_KEY + member.getId());
        if (params.getCategoryCode().equals(CODE_COURSE)) {
            messageSystemService.giveCourse(rel.getMemberId(), content);
        }
    }

    private void addAdvisor(Member member, BenefitsAdd params) {
        Advisor advisor = advisorMapper.selectById(params.getContentId());
        if (advisor != null) {
            AdvisorMemberRel rel = advisorMemberRelMapper.selectOne(new UpdateWrapper<AdvisorMemberRel>().lambda()
                    .eq(AdvisorMemberRel::getMemberId, member.getId())
                    .eq(AdvisorMemberRel::getAdvisorId, params.getContentId()));
            if (rel != null) {
                throw new BaseException("已拥有该顾问身份");
            }
            AdvisorMemberRel effectiveRel = advisorMemberRelMapper.selectOne(new UpdateWrapper<AdvisorMemberRel>().lambda()
                    .eq(AdvisorMemberRel::getMemberId, member.getId())
                    .eq(AdvisorMemberRel::getIsEffective, SURE));
            rel = new AdvisorMemberRel();
            rel.setMemberId(member.getId());
            rel.setAdvisorId(params.getContentId());
            rel.setCreateAt(LocalDateTime.now());
            if (effectiveRel == null) {
                rel.setIsEffective(SURE);
            } else if (advisor.getPreIds() == null || !Set.of(advisor.getPreIds().split(SEPARATED_COMMA))
                    .contains(effectiveRel.getIsEffective().toString())) {
                rel.setIsEffective(NEGATE);
            } else {
                effectiveRel.setIsEffective(NEGATE);
                advisorMemberRelMapper.updateById(effectiveRel);
                rel.setIsEffective(SURE);
            }
            advisorMemberRelMapper.insert(rel);
            memberService.updateRate(member.getId(), advisor.getRate());
        } else {
            throw new BaseException("顾问输入错误");
        }
    }
}
